﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;

namespace TestEffectiveCS
{
    /// <summary>
    /// 将值类型尽可能实现为具有常量性和原子性的类型
    /// </summary>
    public class Test07
    {
        //可变结构Address
        struct Address1
        {
            private string _line;
            private string _city;
            private string _state;
            public string Line { get { return _line; } set { _line = value; } }
            public string City
            {
                get { return _city; }
                set
                {
                    if (value == string.Empty) throw new Exception();
                    _city = value;
                }
            }
            public string State { get { return _state; } set { _state = value; } }
        }

        public class Address2
        {
            private readonly string _line;
            private readonly string _city;
            private readonly string _state;

            public string Line { get { return _line; } }
            public string City { get { return _city; } }
            public string State { get { return _state; } }

            public Address2(string line, string city, string state)
            {
                _line = line;
                _city = city;
                _state = state;

                if (line == string.Empty
                    || city == string.Empty
                    || state == string.Empty) throw new Exception();
            }
        }

        struct Phone
        {
            int _number;
            public int Number { get { return _number; } }
            static Random R = new Random();
            public static Phone GeneratePhoneNumber()
            {
                Phone p = new Phone();
                p._number = R.Next(10000, 1000000000);
                return p;
            }

            public override string ToString()
            {
                return _number.ToString();
            }

        }

        struct PhoneList1
        {
            private readonly Phone[] _phones;

            public PhoneList1(Phone[] phones)
            {
                _phones = phones;
            }

            public IEnumerator Phones
            {
                get { return _phones.GetEnumerator(); }
            }

        }

        struct PhoneList2
        {
            private readonly Phone[] _phones;

            public PhoneList2(Phone[] phones)
            {
                _phones = new Phone[phones.Length];
                phones.CopyTo(_phones, 0);
            }

            public IEnumerator Phones
            {
                get { return _phones.GetEnumerator(); }
            }

        }

        public Test07()
        {
            #region Example Address
            Address1 a1 = new Address1();
            a1.Line = "111 S. Main";
            a1.City = "Anytown";
            a1.State = "IL";
            Console.WriteLine("输入Address1原始值");
            Console.WriteLine("{0,-15}{1,-15}{2,-15}\n", a1.Line, a1.City, a1.State);
            try
            {
                a1.Line = "Ann Arbor";
                a1.City = string.Empty;     //抛异常
                a1.State = "MI";
            }
            catch { }
            Console.WriteLine("Address1被部分修改而变为无效：");
            Console.WriteLine("{0,-15}{1,-15}{2,-15}\n", a1.Line, a1.City, a1.State);

            Address2 a2 = new Address2(
                    "111 S. Main",
                    "Anytown",
                    "IL");
            Console.WriteLine("输入Address2原始值：");
            Console.WriteLine("{0,-15}{1,-15}{2,-15}\n", a2.Line, a2.City, a2.State);
            try
            {
                a2 = new Address2(
                    "Ann Arbor",
                    string.Empty,     //抛异常
                    "MI");
            }
            catch { }
            Console.WriteLine("Address2构造失败，保持原始值不变：");
            Console.WriteLine("{0,-15}{1,-15}{2,-15}\n", a2.Line, a2.City, a2.State);
            try
            {
                a2 = new Address2(
                    "Ann Arbor",
                    "WuHan",     //抛异常
                    "MI");
            }
            catch { }
            Console.WriteLine("正常输出修改后的Address2：");
            Console.WriteLine("{0,-15}{1,-15}{2,-15}\n", a2.Line, a2.City, a2.State);

            #endregion

            #region Example PhoneList
            Phone[] phones = new Phone[10];
            PhoneList1 p1 = new PhoneList1(phones); //引用传递
            PhoneList2 p2 = new PhoneList2(phones); //内部对值进行复制传递
            phones[5] = Phone.GeneratePhoneNumber();
            IEnumerator item1 = p1.Phones;
            item1.Reset();
            Console.Write("\nPhoneList中的Phone数组值被修改\n");
            while (item1.MoveNext()) Console.Write(item1.Current + "\t");

            IEnumerator item2 = p2.Phones;
            item2.Reset();
            Console.Write("\nPhoneList中的Phone数组值未被修改\n");
            while (item2.MoveNext()) Console.Write(item2.Current + "\t");
            #endregion
        }
    }
}
